<template>
    <div class="content">
        <div class="filter">
            <el-form label-width="80px">
                <el-form-item label="菜单过滤">
                    <el-input v-model="filterText" style="width: 240px" placeholder="关键字" />
                </el-form-item>
            </el-form>


            <el-form-item style="margin-left: auto;">
                <div v-show="isEdit" style="padding-right: 40px;">
                    <el-checkbox v-model="loosely" :value="true" label="联动模式" />
                </div>
                <el-button type="primary" v-show="!isEdit" @click="handleEdit" link icon="edit">编辑</el-button>
                <el-button v-show="isEdit" @click="handleCancle" icon="CircleClose">取消</el-button>
                <el-button type="primary" v-show="isEdit" @click="handleSave" icon="CircleCheckFilled">保存</el-button>
            </el-form-item>
        </div>
        <div class="tree">
            <el-tree :data="menuTree" show-checkbox node-key="id" default-expand-all check-on-click-node
                :filter-node-method="filterNode" ref="treeRef" :expand-on-click-node="false" :props="treeProps"
                v-loading="loading" :check-strictly="!loosely">
                <template #default="{ node, data }">
                    <span>{{ node.label }}</span>
                    <span style="padding-left: 10px;" v-if="!data.requiresAuth">
                        <el-text type="success">(开放)</el-text>
                    </span>
                </template>
            </el-tree>
        </div>
    </div>
</template>

<script setup>
import { treeselect } from '@/api/system/menu.js';
import { listSysRoleMenu, saveSysRoleMenu } from "@/api/system/rolemenu.js"
const { proxy } = getCurrentInstance();
const props = defineProps({
    roleId: { type: [Number, String], required: true, default: 0 }
})
const filterText = ref();
const menuTree = ref([]);
const treeRef = ref();
const loading = ref(false);
const isEdit = ref(false);
const role = ref();
const loosely = ref(true);

const customNodeClass = (data, node) => {
    if (!data.children || data.children.length === 0) {
        return null;
    }
    const checkChildren = (children) => {
        let allLeafNodes = true;
        for (const child of children) {
            if (child.children && child.children.length > 0) {
                allLeafNodes = false;
                break;
            }
        }
        return allLeafNodes ? 'is-penultimate' : null; // 根据结果返回
    };
    return checkChildren(data.children);
};

const treeProps = {
    class: customNodeClass,
    label: 'name',
}

watch(
    () => props.roleId,
    (newRoleId) => {
        handleRoleChange()
            .catch((error) => {
                console.error("角色切换处理出错:", error);
            })
            .finally(() => {
                loading.value = false;
            });
    }
);

// 封装加载菜单数据的逻辑
function updateMenus() {
    return getSelectedMenus()
        .then((res) => {
            processData(menuTree.value);
            bindMenus(res);
        })
        .catch((error) => {
            console.error("加载菜单失败:", error);
        });
}

// 封装角色变化后的整体处理逻辑
function handleRoleChange() {
    // 如果正在编辑，则先确认是否保存
    const saveOrCancel = isEdit.value
        ? proxy.$modal.confirm("当前数据正在编辑，是否保存").then(handleSave)
            .catch((error) => {
                if (error === "cancel") {
                    return Promise.resolve();
                }
                return Promise.reject(error);
            })
        : Promise.resolve();

    // 无论是否编辑，都统一加载菜单数据
    return saveOrCancel.then(res => {
        isEdit.value = false;
        loading.value = true;
    }).then(updateMenus)
}


const getTree = () => {
    return treeselect().then(res => {
        menuTree.value = res;
        processData(menuTree.value)
        return res;
    });
}

const processData = (nodes) => {
    nodes.forEach(node => {
        node.disabled = !isEdit.value;
        if (node.children && node.children.length > 0) {
            processData(node.children);
        }
    });
}




watch(filterText, (val) => {
    treeRef.value && treeRef.value.filter(val);
})

const filterNode = (value, data) => {
    if (!value) return true
    value = value.trim();
    return data.name.includes(value)
}

const getSelectedMenus = () => {
    return listSysRoleMenu(props.roleId);
}

const bindMenus = (menus) => {
    treeRef.value.setCheckedKeys([]);
    let checked = menus.map(item => item.id);
    checked.forEach((v) => {
        nextTick(() => {
            treeRef.value.setChecked(v, true, false)
        })
    })
}

const handleEdit = () => {
    isEdit.value = true;
    processData(menuTree.value)
}


const handleSave = () => {
    isEdit.value = false;
    processData(menuTree.value)
    const checkedNodes = treeRef.value.getCheckedKeys();
    const halfCheckedNodes = treeRef.value.getHalfCheckedKeys();
    const nodes = [...checkedNodes, ...halfCheckedNodes];
    return saveSysRoleMenu(props.roleId, nodes).then(() => {
        proxy.$modal.msgSuccess("保存成功");
    }).catch(res => {
        getSelectedMenus(props.roleId).then(res => {
            bindMenus(res);
        })
    });
}

//取消保存
const handleCancle = () => {
    isEdit.value = false;
    updateMenus();
}

onMounted(() => {
    loading.value = true;
    Promise.all([getTree(), getSelectedMenus()]).then(([result1, result2]) => {
        bindMenus(result2);
    }).then(() => {
        loading.value = false;
    })
})

defineExpose({ save: handleSave })



</script>

<style lang="scss">
.content {
    .is-penultimate>.el-tree-node__content {
        /* color: #626aef; */
    }

    .el-tree .el-tree-node.is-penultimate>.el-tree-node__children {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    }

    .is-penultimate>.el-tree-node__children>div {
        /* width: 25%; */
    }
}
</style>
<style lang="scss" scoped>
.content {
    height: 100%;
    display: flex;
    flex-direction: column;

    .filter {
        flex-shrink: 0;
        border-bottom: 1px solid;
        display: flex;
        align-items: center;
    }

    .tree {
        padding-top: 10px;
        flex: 1 auto;
        overflow-y: scroll;
    }
}
</style>